//
//  ExOpenGLESViewController.m
//  OC-Example
//
//  Created by lcj on 2020/12/24.
//  Copyright © 2020 apang.men. All rights reserved.
//

#import <GLKit/GLKit.h>

#import "ExOpenGLESViewController.h"
@interface ExOpenGLESViewController ()<GLKViewDelegate>
@property (nonatomic, strong) GLKBaseEffect * imageBaseEffect;
@property (nonatomic, strong) GLKView * TDGLKView;
@property (nonatomic, strong) GLKBaseEffect * TDSquareBaseEffect;
// 计时器
@property (nonatomic, strong) CADisplayLink *displayLink;
// 弧度
@property (nonatomic, assign) NSInteger angle;
// 顶点缓存区标识符ID
@property (nonatomic, assign) GLuint vertexBuffer;
@end

@implementation ExOpenGLESViewController

- (void)drawImage {
    EAGLContext * context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
    GLKView * glkView = [[GLKView alloc] initWithFrame:CGRectMake(0, 0, 100, 100) context:context];
    glkView.backgroundColor = [UIColor whiteColor];
    glkView.tag = 10010;
    glkView.delegate = self;
    [EAGLContext setCurrentContext:context];
    [self.view addSubview:glkView];
    
    glkView.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;//
    /**
     由于2.0之后呢是绘制三角形，那么一个矩形就是由两个三角形组成的，我这里的分割线是从 左上角到右下角分割的
     */
    GLfloat squareVertextData[] = {
        -0.5, 0.5, 0.0f,    0.0f, 1.0f, //左上
        0.5, 0.5, 0.0f,     1.0f, 1.0f, //右上
        0.5, -0.5, 0.0f,    1.0f, 0.0f, //右下
        
        0.5, -0.5, 0.0f,    1.0f, 0.0f,
        -0.5, -0.5, 0.0f,   0.0f, 0.0f,
        -0.5, 0.5, 0.0f,    0.0f, 1.0f,
    };
    
    glClearColor(0.33, 0.66, 1, 1);//设置背景颜色
    // 开辟顶点缓存区
    GLuint buffer;
    // 1.创建顶点缓存区标识符ID
    glGenBuffers(1, &buffer);
    // 2.绑定顶点缓存区.(明确作用)
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    // 3.将顶点数组的数据copy到顶点缓存区中(GPU显存中)
    glBufferData(GL_ARRAY_BUFFER, sizeof(squareVertextData), squareVertextData, GL_STATIC_DRAW);
    
    /*
     注意点：
        在iOS中，默认情况下，出于性能考虑， 所有顶点着色器的属性(Attribute)变量都是关闭的， 意味着，顶点数据在着色器（服务端）是不可用的。即使你已经使用glBufferData方法，将顶点数据从内存拷贝到顶点缓冲区中(GPU显存中);所以，必须由glEnableVertexAttribArray方法打开通道，指定访问属性，才能让顶点着色器能够访问到从CPU复制到GPU的数据。
     注意：
         数据在GPU端是否可见，即着色器能否读取到数据，由是否启用了对应的属性决定，这就是glEnableVertexAttribArray的功能，允许顶点着色器读取GPU（服务端）数据。
         GLKVertexAttribPosition,        // 顶点
         GLKVertexAttribNormal,          // 法线
         GLKVertexAttribColor,           // 颜色
         GLKVertexAttribTexCoord0,       // 纹理
         GLKVertexAttribTexCoord1

     */
    
    // 顶点坐标数据
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    /*
     参数1: 指定要修改的属性的索引值
     参数2: 每次读取数量(如position是由3个（x,y,z）组成，而颜色是4个（r,g,b,a）,纹理则是2个.)
     参数3: 指定数组中每个组件的数据类型。可用的符号常量有GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, 和 GL_FLOAT，初始值为GL_FLOAT。
     参数4: 指定当被访问时，固定点数据值是否应该被归一化（GL_TRUE）或者直接转换为固定点值（GL_FALSE）
     参数5: 指定连续顶点属性之间的偏移量。如果为0，那么顶点属性会被理解为：它们是紧密排列在一起的。初始值为0
     参数6: 指定一个指针，指向数组中第一个顶点属性的第一个组件。初始值为0
     */
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLfloat *)NULL + 0);
    //参数6:表示从数组中的0索引开始读取，参数2表示连续三个内容都是顶点数据，参数5表示每组顶点数据间隔为5
    
    // 纹理坐标数据
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLfloat *)NULL + 3);
    //参数6:表示从数组中的3索引开始读取，参数2表示连续2个内容都是纹理坐标数据，参数5表示每组顶点数据间隔为5
    
    NSString * filePath = [[NSBundle mainBundle] pathForResource:@"zc_top" ofType:@"png" inDirectory:@"Resource/Document"];
    /*
     纹理坐标默认左下角为原点(0,0)，而iOS坐标系中，默认手机屏幕的左上角为原点(0,0)，所以需要特别注意这一点，需要设置GLKTextureLoaderOriginBottomLeft，不然图片显示的时候，会发生翻转。*/
    NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:@(1), GLKTextureLoaderOriginBottomLeft, nil];
    GLKTextureInfo* textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil];
    //着色器
    _imageBaseEffect = [[GLKBaseEffect alloc] init];
    self.imageBaseEffect.texture2d0.enabled = GL_TRUE;
    self.imageBaseEffect.texture2d0.name = textureInfo.name;
}

- (void)draw3Dsquare {
    EAGLContext * context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
    _TDGLKView = [[GLKView alloc] initWithFrame:CGRectMake(100, 0, 100, 100) context:context];
    _TDGLKView.tag = 10011;
    _TDGLKView.delegate = self;
    [EAGLContext setCurrentContext:context];
    [self.view addSubview:_TDGLKView];
    
    _TDGLKView.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
    _TDGLKView.drawableDepthFormat = GLKViewDrawableDepthFormat24;

    GLfloat squareVertextData[] = {
        // 正
        -0.5,   0.5,    0.5f,       0.0f,   1.0f, //左上
        0.5,    0.5,    0.5f,       1.0f,   1.0f, //右上
        0.5,    -0.5,   0.5f,       1.0f,   0.0f, //右下

        0.5,    -0.5,   0.5f,       1.0f,   0.0f,
        -0.5,   -0.5,   0.5f,       0.0f,   0.0f,
        -0.5,   0.5,    0.5f,       0.0f,   1.0f,

        //后
        -0.5,   0.5,    -0.5f,       0.0f,  1.0f, //左上
        0.5,    0.5,    -0.5f,       1.0f,  1.0f, //右上
        0.5,    -0.5,   -0.5f,       1.0f,  0.0f, //右下

        0.5,    -0.5,   -0.5f,       1.0f,  0.0f,
        -0.5,   -0.5,   -0.5f,       0.0f,  0.0f,
        -0.5,   0.5,    -0.5f,       0.0f,  1.0f,
        
        // 右
        0.5,    0.5,    0.5,        0.0f,   1.0f,
        0.5,    0.5,    -0.5,       1.0f,   1.0f,
        0.5,    -0.5,   -0.5,       1.0f,   0.0f,

        0.5,    -0.5,   -0.5,       1.0f,   0.0f,
        0.5,    -0.5,   0.5,        0.0f,   0.0f,
        0.5,    0.5,    0.5f,       0.0f,   1.0f,
        
        //左
        -0.5,    0.5,    0.5,        0.0f,   1.0f,
        -0.5,    0.5,    -0.5,       1.0f,   1.0f,
        -0.5,    -0.5,   -0.5,       1.0f,   0.0f,

        -0.5,    -0.5,   -0.5,       1.0f,   0.0f,
        -0.5,    -0.5,   0.5,        0.0f,   0.0f,
        -0.5,    0.5,    0.5f,       0.0f,   1.0f,
        
        //上
        -0.5,   0.5,   -0.5,       0.0f,   1.0f,
        0.5,    0.5,   -0.5,       1.0f,   1.0f,
        0.5,    0.5,   0.5,        1.0f,   0.0f,

        0.5,     0.5,   0.5,        1.0f,   0.0f,
        -0.5,    0.5,   0.5,        0.0f,   0.0f,
        -0.5,    0.5,   -0.5f,      0.0f,   1.0f,

        //下
        -0.5,   -0.5,   -0.5,       0.0f,   1.0f,
        0.5,    -0.5,   -0.5,       1.0f,   1.0f,
        0.5,    -0.5,   0.5,        1.0f,   0.0f,

        0.5,     -0.5,   0.5,        1.0f,   0.0f,
        -0.5,    -0.5,   0.5,        0.0f,   0.0f,
        -0.5,    -0.5,   -0.5f,      0.0f,   1.0f,
    };
    glClearColor(0.75, 0.5, 0.25, 1);//设置背景颜色
    GLuint buffer;
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(squareVertextData), squareVertextData, GL_STATIC_DRAW);
    
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLfloat *)NULL + 0);
    
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLfloat *)NULL + 3);
    glDepthRangef(1, 0);
    
    NSString * filePath = [[NSBundle mainBundle] pathForResource:@"zc_top" ofType:@"png" inDirectory:@"Resource/Document"];
    
    UIImage *image = [UIImage imageWithContentsOfFile:filePath];
    NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:@(1), GLKTextureLoaderOriginBottomLeft, nil];
    GLKTextureInfo* textureInfo = [GLKTextureLoader textureWithCGImage:image.CGImage options:options error:nil];
    _TDSquareBaseEffect = [[GLKBaseEffect alloc] init];
    self.TDSquareBaseEffect.texture2d0.enabled = GL_TRUE;
    self.TDSquareBaseEffect.texture2d0.name = textureInfo.name;
    self.TDSquareBaseEffect.texture2d0.target = textureInfo.target;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor whiteColor];
    [self drawImage];
    [self draw3Dsquare];
    self.angle = 0;
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(reDisplay)];
    [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}

- (void)reDisplay {
    // 计算旋转度数
    self.angle = (self.angle + 1) % 360;
    // 修改baseEffect.transform.modelviewMatrix
    self.TDSquareBaseEffect.transform.modelviewMatrix = GLKMatrix4MakeRotation(GLKMathDegreesToRadians(self.angle), 0.3, 1, -0.7);
    // 重新渲染
    [self.TDGLKView display];
}

/**
 *  渲染场景代码
 */
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
    if (view.tag == 10010) {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        //启动着色器
        [self.imageBaseEffect prepareToDraw];
        glDrawArrays(GL_TRIANGLES, 0, 6);
    }
    if (view.tag == 10011) {
        glEnable(GL_DEPTH_TEST);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        //启动着色器
        [self.TDSquareBaseEffect prepareToDraw];
        glDrawArrays(GL_TRIANGLES, 0, 36);
    }
}

- (void)dealloc {
    if ([EAGLContext currentContext] == self.TDGLKView.context) {
        [EAGLContext setCurrentContext:nil];
    }
    //displayLink 失效
    [self.displayLink invalidate];
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end
